package com.excellent.mvvm.utils

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Environment
import android.util.Log
import kotlinx.coroutines.sync.withLock
import java.io.BufferedReader
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.text.DecimalFormat
import kotlin.math.log10


object FileManager {
    fun getDownloadFolderImageOutputFile(suffix: String): File {
        return File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absoluteFile.toString() + File.separator + suffix + ".jpg")
    }

    fun getDownloadFolderOutputFile(suffix: String): File {
        return File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absoluteFile.toString() + File.separator + suffix + ".log")
    }

    fun readableFileSize(size: Long): String {
        if (size <= 0) return "0"
        val units = arrayOf("B", "kB", "MB", "GB", "TB")
        val digitGroups = (log10(size.toDouble()) / log10(1024.0)).toInt()
        return DecimalFormat("#,##0.#").format(size / Math.pow(1024.toDouble(),digitGroups.toDouble())) + " " + units[digitGroups]
    }

    fun getDirSize(dir: File): Long {
        var size: Long = 0
        for (file in dir.listFiles()) {
            if (file != null && file.isDirectory) {
                size += getDirSize(file)
            } else if (file != null && file.isFile) {
                size += file.length()
            }
        }
        return size
    }

    fun deleteCache(context: Context) {
        try {
            val dir = context.cacheDir
            deleteDir(dir)
        } catch (ignored: Exception) {
        }
    }

    fun deleteDir(dir: File?): Boolean {
        if (dir != null && dir.isDirectory) {
            val children = dir.list()
            for (child in children) {
                val success = deleteDir(File(dir, child))
                if (!success) {
                    return false
                }
            }
            return dir.delete()
        } else if (dir != null && dir.isFile) {
            return dir.delete()
        } else {
            return false
        }
    }

    /**
     * 返回一个文件可以临时存放下载的音频，暂时不做音频的缓存，只能临时下载临时播放.
     *
     * @return
     */
    fun getTempVoiceFile(context: Context): File {
        return File(context.cacheDir.absoluteFile.toString() + File.separator + "voice")
    }

    /**
     * 返回一个文件可以临时存放下载的音频，暂时不做音频的缓存，只能临时下载临时播放.
     *
     * @return
     */
    fun getTempUrlFileName(context: Context, name: String): File {
        return File(context.cacheDir.absoluteFile.toString() + File.separator + "open_file" + File.separator + name + ".png")
    }


    fun getAgoraSDKLogPath(context: Context): File {
        return File(context.cacheDir.absoluteFile.toString() + File.separator + "agorasdk" + File.separator + "agorasdk.log")
    }

    /**
     * 获取打印日志的路径
     * @return
     */
    fun getCacheFilePrinter(context: Context): String {
        val path = getCachePath(context) //根据手机有无外内存决定是否存在外内存还是本机内存
        val file = File(path + File.separator + "printer")
        if (!file.exists()) {
            file.mkdir()
        }
        val finallyPath = path + File.separator + "printer"
        return finallyPath
    }

    /**
     * 获取app缓存路径
     * @param context
     * @return
     */
    fun getCachePath(context: Context): String {
        val cachePath: String
        if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState() || !Environment.isExternalStorageRemovable()) {
            //外部存储可用
            val file = context.externalCacheDir
            cachePath = if (file == null) {
                context.cacheDir.path
            } else {
                file.path
            }
        } else {
            //外部存储不可用
            cachePath = context.cacheDir.path
        }
        return cachePath
    }


    /**
     * 返回一个图片可以临时存放从外部放到沙盒
     * @return
     */
    fun getTempSendImgFile(context: Context, name: String): File {
        val file = File(context.cacheDir.absoluteFile.toString() + File.separator + "temp_img")
        if (!file.exists()) {
            file.mkdir()
        }
        return File(context.cacheDir.absoluteFile.toString() + File.separator + "temp_img/" + name)
    }

    /**
     * 根据uri获取bitmap
     * @param context
     * @param uri
     * @return
     */
    fun getBitmapFormUri(context: Context, uri: Uri?): Bitmap? {
        try {
            val parcelFileDescriptor = context.contentResolver.openFileDescriptor(
                uri!!, "r", null
            )
            val fileDescriptor = parcelFileDescriptor!!.fileDescriptor
            val bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
            parcelFileDescriptor.close()
            return bitmap
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } catch (ioException: IOException) {
            ioException.printStackTrace()
        }
        return null
    }

    //保存Bitmap至本地
    fun saveBitmap2SelfDirectroy(
        bitmap: Bitmap,
        file: File?
    ): File? {
        try {
            val fos = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.JPEG, 75, fos)
            fos.flush()
            fos.close()
        } catch (e: Exception) {
            return null
        }
        return file
    }
    val f = "te"
    val l = "mp"
    /**
     * 写入临时数据到本地
     */
    fun tempFilmToLocal(context: Context,data: String){
        writeDataToFile(context,"$f$l",data)
    }

    /**
     * 写入文件数据
     * val fileName = "myfile.txt"
     * val data = "Hello, World!"
     *
     * writeDataToFile(this, fileName, data)
     */
    fun writeDataToFile(context: Context, fileName: String, data: String) {
        // 获取本地沙盒目录中的文件对象
        val pathRoot = getCachePath(context) //根据手机有无外内存决定是否存在外内存还是本机内存
        val parentPath = "$pathRoot${File.separator}caches"
        Log.d("FileManager","writeDataToFile ${parentPath}")
        val file = File(parentPath, fileName)

        // 检查父目录是否存在，如果不存在则创建
        val parentDir = file.parentFile
        if (parentDir != null && !parentDir.exists()) {
            parentDir.mkdirs()  // 创建父目录
        }
        // 检查文件是否存在
        if (!file.exists()) {
            // 如果文件不存在，创建新文件
            try {
                file.createNewFile()
            } catch (e: Exception) {
                e.printStackTrace()
                return
            }
        }
        try {
            // 在数据后加上换行符
            val dataWithNewLine = "$data${System.lineSeparator()}"
            // 打开文件输出流并写入数据 append表示在后面添加
            FileOutputStream(file,true).use { outputStream ->
                outputStream.write(dataWithNewLine.toByteArray())
                // outputStream.flush() 不需要手动调用，因为 close() 会自动刷新并关闭流
            }
            Log.d("FileManager","writer close()")
            Log.d("FileManager","writeDataToFile write =${data}")
        }catch (e:Exception){
            Log.d("FileManager","writeDataToFile e=${e.message}")
        } finally {

        }
    }

    fun clearCFile(context: Context, fileName: String) {
        // 获取本地沙盒目录中的文件对象
        val pathRoot = getCachePath(context) //根据手机有无外内存决定是否存在外内存还是本机内存
        val parentPath = "$pathRoot${File.separator}caches"
        Log.d("FileManager","writeDataToFile ${parentPath}")
        val file = File(parentPath, fileName)

        // 检查父目录是否存在，如果不存在则创建
        val parentDir = file.parentFile
        if (parentDir != null && !parentDir.exists()) return

        if (file.exists()) {
            // 使用 FileOutputStream 创建一个新的空文件流
            val fos = FileOutputStream(file)
            fos.write(ByteArray(0))  // 写入空字节，清空文件内容
            fos.close()  // 关闭文件流
        }
    }

    /**
     * 读取文件数据
     * val fileContent = readDataFromFile(this, fileName)
     * println(fileContent)  // 输出文件内容
     */
    fun readDataFromFile(context: Context, fileName: String): String {
        val inputStream = context.openFileInput(fileName)
        val reader = BufferedReader(InputStreamReader(inputStream))
        val stringBuilder = StringBuilder()

        try {
            var line: String?
            while (reader.readLine().also { line = it } != null) {
                stringBuilder.append(line).append("\n")
            }
        } finally {
            reader.close()
        }

        return stringBuilder.toString().trim()
    }


}
